package com.yangyouli.unity_demo_server.util;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.log4j.Logger;

public class ScannerUtil {
	static Logger log = Logger.getLogger(ScannerUtil.class);
	
	/**
	 * 扫描并得到包下面的所有类的全名
	 * @param packagePath
	 * @return 类全称的集合
	 */
	public static List<String> scanPackage (String packagePath) {
		URL url = ScannerUtil.class.getClassLoader().getResource(packagePath.replaceAll("\\.", "/"));
		String protocol = url.getProtocol();
        if ("file".equals(protocol)) {  
            // 本地自己可见的代码  
        	return scanPackageNotJar(packagePath);
        } else if ("jar".equals(protocol)) {  
            // 引用jar包的代码  
			return scanJarPackage(packagePath);
        } else {
        	return null;
        }
	}
	
	/**
	 * 扫描 pckagePath 包下的所有类（包含子包下的所有类），返回该包下的所有类的全路径（包名加类名）
	 * @param packagePath 包名
	 * @return 类名的集合
	 */
	private static List<String> scanPackageNotJar (String packagePath) {
		List<String> classWholeNameList = new ArrayList<String>();
		List<String> childClassWholeNameList = null;
		// 将所有 . 替换成 /
		String packagePathReplaced = packagePath.replaceAll("\\.", "/");
		URL url = ScannerUtil.class.getClassLoader().getResource(packagePathReplaced);
		String filePath = null;
		try {
			filePath = URLDecoder.decode(url.getFile(), "UTF-8");
		} catch (UnsupportedEncodingException e) {
			log.error("给包路径转码时发生异常", e);
		}
		File file = new File(filePath);
		String[] fileNameList = file.list();
		for (String fname : fileNameList) {
			File childFile = new File(filePath + "/" + fname);
			// 是文件夹继续遍历
			if (childFile.isDirectory()) {
				childClassWholeNameList = scanPackage(packagePath + "." + childFile.getName());
			} else {
				// 是类则添加到列表中
				// 得到类名的全路径
				String classWholeName = packagePath + "." + childFile.getName();
				// 如果为 .class 后缀的文件，则去除 .class 后缀且添加到 classWholeNameList 中
				if (classWholeName.contains(".class")) {
					classWholeName = classWholeName.substring(0, classWholeName.length() - 6);
					classWholeNameList.add(classWholeName);
				}
			}
		}
		// 将 childClassWholeNameList 中的元素添加到 classWholeNameList 中
		if (childClassWholeNameList != null) {
			for (String str : childClassWholeNameList) {
				classWholeNameList.add(str);
			}
		}
		return classWholeNameList;
	}
	
	/**
	 * 扫描 jar 包中某个包下的所有类
	 * @param packagePath
	 * @return
	 */
	private static List<String> scanJarPackage (String packagePath) {
		List<String> classWholeNameList = new ArrayList<String>();
		
		String packagePathReplaced = packagePath.replaceAll("\\.", "/");
		JarFile jarFile = null;
		URL url = ScannerUtil.class.getClassLoader().getResource(packagePathReplaced);
		try {
			JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
			jarFile = jarURLConnection.getJarFile();
		} catch (IOException e) {
			log.error("扫描 jar 包中某个包下的所有类发生了异常", e);
		}
		
		Enumeration<JarEntry> jarEntries = jarFile.entries();
		while(jarEntries.hasMoreElements()) {
			JarEntry jarEntry = jarEntries.nextElement();
			String jarEntryName = jarEntry.getName();
			
            //这里我们需要过滤不是class文件和不在basePack包名下的类
            if (jarEntryName.contains(".class") && jarEntryName.replaceAll("/",".").startsWith(packagePath)) {
                String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replace("/", ".");
                classWholeNameList.add(className);
            }
		}
		return classWholeNameList;
	}
}
